﻿using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Web;

namespace Gonte.Web
{
    /// <summary>
    /// Converts resources to a JSON string
    /// </summary>
    public static class ResourcesToJsonConverter
    {
        public static string Convert(ResourceSet resourceSet, string language)
        {
            string json =
@"var app=app||{{}};app.lang={{lang:""{0}""{1}}};";

            StringBuilder stringBuilder = new StringBuilder();
            IDictionaryEnumerator enumerator = resourceSet.GetEnumerator();

            while (enumerator.MoveNext())
            {

                stringBuilder.Append(",");
                stringBuilder.Append(enumerator.Key);

                string value = (string)enumerator.Value;

                if (value.Contains(@""""))
                {
                    stringBuilder.Append(@":'");
                    stringBuilder.Append(value);
                    stringBuilder.Append(@"'");
                }
                else
                {
                    stringBuilder.Append(@":""");
                    stringBuilder.Append(value);
                    stringBuilder.Append(@"""");
                }
            }

            string data = stringBuilder.ToString();
            return string.Format(json, language, data);
        }

        /// <summary>
        /// Retrieves the resource as a JSON string
        /// </summary>
        /// <param name="context">The HttpContext object</param>
        /// <param name="resourceName">The name of the resource to retrieve</param>
        /// <param name="assemblyName">The name of assembly this resource is</param>
        /// <returns>The resource as a JSON string</returns>
        public static string GetResourceAsJson(HttpContext context, string resourceName, Func<Assembly> assemblyRetriever)
        {
            CultureInfo culture = context.Request.GetCulture();
            string language = culture.Name;
            Assembly assembly = assemblyRetriever();
            string contentKey = string.Format("{0}:{1}:{2}", assembly.FullName, resourceName, language);
            string content = (string)context.Cache[contentKey];

            if (content == null)
            {
                ResourceManager resourceManager = GetResourceManager(resourceName, assembly);
                ResourceSet resourceSet = resourceManager.GetResourceSet(culture, true, true);
                content = ResourcesToJsonConverter.Convert(resourceSet, language);
                context.Cache[contentKey] = content;
            }
            return content;
        }

        private static ResourceManager GetResourceManager(string resourceName, Assembly assembly)
        {
            string key = string.Format("{0}:{1}", assembly.FullName, resourceName);

            if (!_cachedManagers.ContainsKey(key))
            {
                _cachedManagers[key] = new ResourceManager(resourceName, assembly);
            }

            return _cachedManagers[key];
        }

        #region Helpers

        #endregion

        #region Fields

        /// <summary>
        /// Caches the resource managers to reuse them, the key is the resource name that it should be unique to the application
        /// </summary>
        private static IDictionary<string, ResourceManager> _cachedManagers = new ConcurrentDictionary<string, ResourceManager>();

        #endregion
    }
}
